#This script runs all the setup sql in the proper order of execution

#import all modules needed
import os, re, sys, sqlalchemy, argparse, platform, inspect
from sqlalchemy import select, create_engine, func
from sqlalchemy.orm import scoped_session, sessionmaker

if __name__ == '__main__':

  desc = "This script initializes the project configuration."
  parser = argparse.ArgumentParser(description=desc)
  parser.add_argument('-d', '--dir', required=True, dest='dir', help='Directory of the new Spyrim project. The directory given should contain the Makefile.py and the other project directories. (Required)')

  # args = parser.parse_args()
  args = parser.parse_args(['-d','C:/MaxFranks/pypi/some_project/analysis_project'])

  # add models to sys.path
  model_dir = os.path.normpath(args.dir+'/src/models')
  if((model_dir in sys.path) == False):
    sys.path.append(model_dir)
  
  from config_model import *

  def new_session(eng, output=False):
    """creates a new database session from an engine"""
    return scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=create_engine(eng, echo=output)))
  
  def new_session_from_engine(eng, autocommit=False):
    """creates a new database session from an engine"""
    return scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=eng))
  
  def new_engine(eng, output=False):
    """creates a new database engine"""
    return create_engine(eng, echo=output)
  
  def new_profile(_session):
    """creates a new analysis profile"""
    print "Analysis Profile:\n\n"
    host = raw_input("Database Host (leave blank if no database is being used): ")
    data = raw_input("Data directory (top level data directory for this analysis event): ")
  
    def_results = os.path.normpath(data+"/results")
    results = raw_input("Results directory [%s]: "%def_results)
    if len(results.strip()) == 0:
      results = def_results
  
    def_html = os.path.normpath(data+"/results/html")
    html = raw_input("HTML directory [%s]: "%def_html)
    if len(html.strip()) == 0:
      html = def_html
    
    ap = AnalysisProfile(host, data, html, results)
    
    print "\nSummary\n-------\n"
    print "Host: %s" % ap.host
    print "Data Directory: %s" % ap.data_directory
    print "Results Directory: %s" % ap.results_directory
    print "HTML Directory: %s" % ap.html_directory
    
    
    _choice = raw_input("\nDoes this look correct? ")
    if 'y' in _choice.lower():
      _session.add(ap)
      _session.commit()
    
      return ap 
    return None
  
  def new_driver(_session):
    """creates a new database driver"""
    from config_model import Driver
    import os
    print "Driver:\n\n"
    drvr = raw_input("Database Driver (ie. sqlite:/// or mysql+mysqldb://): ")
    alias = raw_input("Driver Alias: (ie. python_mysql): ")
    
    drv = Driver(drvr, alias)
    
    print "\nSummary\n-------\n"
    print "Driver: %s" % drv.driver
    print "Driver Alias: %s" % drv.alias
    
    if 'y' in raw_input("\nDoes this look correct [y]? ").lower():
      _session.add(drv)
      _session.commit()
      return drv
    
    return None
  
  cwd = os.getcwd()
  print cwd
  os.chdir(args.dir)
  print os.getcwd()
  # engine = new_engine("sqlite:///config/config.db", False)
  engine = new_engine("sqlite:///./config/config.db", False)
  
  # create all tables in config_model
  print "Creating config tables..."
  for m in os.listdir(model_dir):
      if m.endswith(".py") and m.startswith('config'):
        
        #import model as Python module
        module = __import__(m.split(".")[0])
        
        # get classes in model script
        for clz in inspect.getmembers(module, inspect.isclass):
          
          ## gets the parent class
          clazz = inspect.getmro(clz[1])
          
          ## can't be a base class
          if len(clazz) > 0:
            
            # is it a sqlalchemy class
            if clazz[1].__name__ == "Base":
              
              # creates the table from the class
              clazz[0].__table__.create(engine, checkfirst=True)
  
  # initialize drivers table
  session = new_session_from_engine(engine)
  drivers = [("sqlite:///", "sqlite_file"),
            ("mysql+mysqldb://", "python_mysql"),]
  
  print "Loading database drivers..."
  from config_model import Driver
  for driver, db_uid in drivers:
    drvr = Driver(driver, db_uid)
    
    matches = session.query(Driver).filter(Driver.driver == driver).all()
    if len(matches) > 1:
      for match in matches[1:]:
        session.delete(match)
    elif len(matches) == 0:
      session.add(drvr)
  
  # create inital configuration with default options
  options = [("root_user", "root")]
  print "Loading default options..."
  
  from config_model import Option
  for key, value in options:
    opt = Option(key, value)
    
    matches = session.query(Option).filter(Option.key == key).all()
    if len(matches) > 0:
      continue
    elif len(matches) == 0:
      session.add(opt)
  
  session.commit()
  
  # initial analysis profile
  aes = session.query(AnalysisProfile).all()
  selected_ae = None
  
  if len(aes) == 0:
    selected_ae = new_profile(session)
  else:
    
    while(True):
      
      print "\n Please select the host and data dir for this configuration: "
      print " Or, simply press ENTER to create a new data analysis profile.\n"
      
      for ae in aes:
        print "  %i). %s (%s)" % (ae.id, ae.host, ae.data_directory)
      
      choice = raw_input("\n Enter choice: ")
      choice = choice.strip()
      
      if len(choice) != 0:
        selected_ae = session.query(AnalysisProfile).filter(AnalysisProfile.id == choice).all()
        
        if selected_ae:
          selected_ae = selected_ae[0]
          break
        else:
          continue
        
      else:
        selected_ae = new_profile(session)
  
        if selected_ae:
          break
        else:
          continue
  
    print
    print " %s %s" % ("Host:".ljust(25), selected_ae.host)
    print " %s %s" % ("Data directory:".ljust(25), selected_ae.data_directory)
    print " %s %s" % ("Results directory:".ljust(25), selected_ae.results_directory)
    print " %s %s" % ("Html directory:".ljust(25), selected_ae.html_directory)
  
  
  drvs = session.query(Driver).all()
  selected_drv = None
  
  while(True):
    
    print "\n Please select the database driver for this configuration: "
    print " Or, simply press ENTER to create a driver.\n"
    
    for drv in drvs:
      print "  %i). %s (%s)" % (drv.id, drv.driver, drv.alias)
    
    choice = raw_input("\n Enter choice: ")
    choice = choice.strip()
    
    if len(choice) != 0:
      selected_drv = session.query(Driver).filter(Driver.id == choice).all()
      
      if selected_drv:
        selected_drv = selected_drv[0]
        break
      else:
        continue
    else:
      selected_drv = new_driver(session)
  
      if selected_drv:
        break
      else:
        continue
  
  print
  print " %s %s" % ("Alias:".ljust(12), selected_drv.alias)
  print " %s %s" % ("Driver:".ljust(12), selected_drv.driver)
  
  while(True):
    
    conf_name = raw_input("\n Enter the name for this configuration: ")
    
    if len(conf_name.strip()) == 0:
      print "\n  The configuration name cannot be blank!"
      continue
    else:
      conf = Config(conf_name, selected_ae.id, selected_drv.id)
      
      if len(session.query(Config).filter(Config.name == conf_name).all()) > 0:
        print " Configuration names must be unique!"
        continue
      
      session.add(conf)
      session.commit()
      break
  
  opt = Option('current_profile', conf_name)
  
  session.add(opt)
  session.commit()
  session.close()
  
  os.chdir(cwd)
  
  print "\n Done."
